#ifndef MAIN_H
#define MAIN_H

//------------------------- Free Libraries
#include "globals.h"
#include <stdint.h>
#include <stdio.h>

#ifdef atmega1280
#include "mmc.h"
#endif

typedef unsigned char byte;

typedef struct _typAdcData
{
	uint8_t		nId;
	uint16_t	nAdc[8];
} _typAdcData;

typedef struct _typCPUStats
{
	float threadTime;
} _typCPUStats;

typedef struct _typCPUInfo
{
	struct _typCPUStats mCPUStats;
	uint16_t			nTicks;
	uint32_t			nTicksMS;
} _typCPUInfo;

typedef struct _typSwAdcInput
{
	uint8_t		OnOff[SWADC_CNT - SWITCH_CNT];
	uint16_t	value[SWADC_CNT - AD_INPUTS_CNT];
} _typSwAdcInput;

typedef struct _typSwInput
{
	uint8_t		value;
	uint8_t		bounce;
} _typSwInput;
typedef struct _typAdInput
{
	uint16_t	Raw;		/* Raw Values from read */
	union {
		float	Lookup;		/* Lookup value */
		uint8_t	Bytes[4];	/* Raw Bytes */
	};
	uint8_t		Bits;		/* Bit Resoltuion */
} _typAdInput;
typedef struct _typOutput
{
	uint8_t		OnOff;		/* On or Off state of the output		*/
	union {
		float	Value;		/* Float value of the output			*/
		uint8_t	Bytes[4];	/* Bytes of the float for easy access	*/
	} ;						/* Value = 0 - 1						*/
} _typOutput;
typedef struct _typConsult
{
	uint32_t	BitSet;					/* Consult bitset */
	uint8_t		Packet[CONSULT_BUFFER];	/* Consult Packet */
	uint16_t	m_RPM ;
	uint16_t	m_AFM ;
	uint8_t		m_TPS ;
	uint16_t	m_MAP ;
	uint8_t		m_SPEED ;
	uint8_t		m_TEMP ;
	uint8_t		m_LOAD ;
	uint16_t	m_INJ ;
	uint8_t		m_IGN ;
	uint8_t		m_BVOLT ;
} _typConsult;

typedef struct _typTraceData
{
	uint16_t	Address;
	uint8_t		Data[16];
} _typTraceData;

typedef struct _typGlobalData
{
	uint8_t				Protocol;
	struct _typConsult	Consult;							/* Consult Data */
	struct _typAdInput	AdInputs[AD_INPUTS_CNT];			/* AD Inputs */
	struct _typSwInput	SwInputs[SWITCH_CNT];				/* Switch Inputs */
	struct _typOutput	Outputs[OUTPUT_CNT];				/* Outputs */
	uint32_t			Triggers;							/* Triggers */
	uint8_t				FlashMap;							/* Flash Map Select */
	struct _typSwAdcInput	SwAdcInputs;					/* Switch/ADC Inputs */
	struct _typCPUInfo		mCPUInfo;
	struct _typTraceData	mTraceData;
} _typGlobalData;
typedef void (*voidFncPtr16)(void*);

typedef struct _typTimers
{
	voidFncPtr16	mFncPtr;								/* Pointer to function to execute */
	int16_t			mFncParam ;								/* Paramater to pass to function */
	uint32_t		mOverflowCnt ;							/* Overflow Counter */
	uint32_t		mOverflowReq;							/* Overflows required to fire */
	uint8_t			mBRecuring:1,							/* Defined a Recuring Timer */
					mRunning:1,								/* If the thread is still running */
//					mBackground:1,							/* Defines a background task, means it can run all the time */
					mPriority:6;							/* Defines the prioity level, 1 being highest */
} _typTimers;

typedef struct _typOutputMem
{
	uint8_t			Initialised:1,
					OutputNumber:7;
	uint8_t			Data[68];
} _typOutputMem;

typedef union _typAddress
{
	uint32_t	nAddress;
	uint8_t		nBytes[4];
} _typAddress;

void flashRead(uint32_t* address, uint16_t* length);
void flashWrite(uint32_t* address, uint16_t* length, uint8_t* Buffer);
void flashCopy(uint32_t* from, uint32_t* to, uint32_t* length);
void eepromRead(uint16_t address, uint16_t* length);
void eepromWrite(uint16_t address, uint16_t* length, uint8_t* Buffer);
uint8_t flashEraseAll(uint8_t Bank);
uint8_t flashErase(uint32_t* Address);
void comm_usb_handler(uint8_t* buffer, uint16_t nLength);

int main(void) __attribute__((noreturn));
void Initialise(void);
void InitialiseIO(void);
//void getInputs(void);
void Delay(uint16_t ms);

void AddressReset(void);
void AddressInit(_typAddress* address);
void modeReadWrite(void);
void modeSendWriteCmd(void);
void SecuritySet(uint8_t Cmd, uint8_t* Buffer);
uint8_t SecurityCheck(uint8_t LevelRequired);
uint8_t SecurityUnlockCheck(uint8_t FunctionCode);

void FrameGetInfo(void);
void FrameUpload(void);
void FrameResponse(unsigned char Response) ;
void FrameCommand(unsigned char* pchBuffer);

void setSw2(uint8_t num, uint8_t value);
void setMAD2(uint8_t num, uint16_t* value);
void setMAD(uint8_t num, uint16_t * value);
void setMADLU(uint8_t num, float* value);
void setSw(uint8_t num, uint8_t value);
void SetMap(uint8_t Map);
void ADlookupNum(uint8_t Num);

float getFloatS(uint16_t Address);
float getFloat(uint16_t Address, uint8_t Num);
float getVarVal(uint8_t Val);
float getVarValReal(uint8_t Val, uint16_t AUOffset);

uint8_t Compare(float* ValueOne, float* ValueTwo, uint8_t *Comparison);
//inline uint8_t logicalOperation(uint8_t* Operation, uint8_t* ValOne, uint8_t* ValTwo);

uint8_t TriggerCalc(uint16_t Address, uint8_t* State, uint32_t* Triggers, uint8_t TrigerNum);

float calcDAC (uint8_t *OnOff);
uint8_t OutputsCalculate(uint16_t Address, struct _typOutput *Output, struct _typOutputMem *State);
float OutputLookup(uint16_t Address, float* Min, float* Max, float* Value);
uint16_t OutputLookupWord(uint16_t Address, float Min, float Max, float* Value, float Points);
void OutputOnOff(uint16_t Address, float* Value, uint8_t* State);
float ADlookup(uint16_t Address, uint16_t Value);
float ALUlookup(uint8_t aluNum, uint16_t AUOffset);
float ALUOperate(float* valBase, float* valOperator, uint8_t Operator);
void setConsultPacket(uint8_t* buffer, uint8_t bytes, uint32_t BitSet);

void BikTimerMaster(void);
uint8_t BikTimerInit(void (*BikTmrfunc)(void* param), int16_t Paramater, uint32_t Timeout, uint32_t TimeoutOffset, uint8_t Recuring, uint8_t Priority);
void InitialiseConsult(void);
void tmrFrameUpload(void* typTimer);
void tmrConsultInit(void* typTimer);
void tmrGetInputs(void* typTimer);
void tmrGetAdc(void* typTimer);
void tmrOutputsSet(void* typTimer);
void tmrTriggerSet(void* typTimer);
void tmrFrameRecieve(void* typTimer);
void tmrTest(void* typTimer);
void tmrTurboTimer(void* typTimer);
void tmrCpuStats(void* typTimer);
void tmrADLookup(void* typTimer);

// Diagnostics functions
uint8_t diagRxClk(void);
uint8_t diagRxTx(void);
uint8_t diagFlashMem(uint8_t Bank);

// Emualtor functions
void tmrEmulator(void* typTimer);
void EmulatorRPMInitialise(void);
void EmulatorRPMSet(void);
void EmulatorRPMSync(void);

// Testing Apllications
void tstOuts(void);
void tstOuts2(void);
#endif
